package com.example.springboottest.example.zookeeper.distributedLock;

import com.example.springboottest.example.zookeeper.ZKclient;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.recipes.locks.InterProcessMutex;

/**
 * Zlock 实现的主要价值是展示一下分布式锁的原理和基础开发。在实际的开发中，如果需要使
 * 用到分布式锁，不建议去自己“重复造轮子”，而建议直接使用 Curator 客户端中的各种官方实现
 *  的分布式锁，例如其中的 InterProcessMutex 可重入锁
 *
 *  InterProcessMutex是按照顺序执行的分布式锁
 *  如果是开关锁，直接创建一个固定的临时节点就可以了
 **/
public class ZkLockTester {

    public static void main(String[] args) {
        try {
//            new ZkLockTester().testLock();
            new ZkLockTester().testzkMutex();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    int count = 0;

    public void testLock() throws InterruptedException {
        for (int i = 0; i < 2; i++) {
            FutureTaskScheduler.add(() -> {
                //创建锁
                ZkLock lock = new ZkLock();
                lock.lock();
                //每条线程，执行10次累加
                for (int j = 0; j < 10; j++) {
                    //公共的资源变量累加
                    count++;
                }
                try {
                    System.out.println("获取到锁,开始执行业务操作");
                    Thread.sleep(1000);
                    System.out.println("业务操作执行完毕");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("count = " + count);
                //释放锁
                lock.unlock();

            });
        }

        Thread.sleep(Integer.MAX_VALUE);
    }

    /**
     * Zlock 实现的主要价值是展示一下分布式锁的原理和基础开发。在实际的开发中，如果需要使
     * 用到分布式锁，不建议去自己“重复造轮子”，而建议直接使用 Curator 客户端中的各种官方实现
     * 的分布式锁，例如其中的 InterProcessMutex 可重入锁
     *
     * @throws InterruptedException
     */
    public void testzkMutex() throws InterruptedException {

        CuratorFramework client = ZKclient.instance.getClient();
        final InterProcessMutex zkMutex =
                new InterProcessMutex(client, "/mutex");

        for (int i = 0; i < 10; i++) {
            FutureTaskScheduler.add(() -> {

                try {
                    //获取互斥锁
                    zkMutex.acquire();

                    for (int j = 0; j < 10; j++) {
                        //公共的资源变量累加
                        count++;
                    }
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("count = " + count);
                    //释放互斥锁
                    zkMutex.release();

                } catch (Exception e) {
                    e.printStackTrace();
                }

            });
        }

        Thread.sleep(Integer.MAX_VALUE);
    }
}
